package com.kakarote.oa.common.repetitionstrategy;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.kakarote.oa.entity.BO.OaEventDTO;
import com.kakarote.oa.entity.PO.OaEvent;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 每月循环策略
 *
 * @author hmb
 */
@Component("Monthly")
public class MonthlyStrategy extends AbstractRepetitionStrategy {

    @Override
    public List<OaEventDTO> processQuery(List<OaEvent> oaEventList, long startTime, long endTime) {
        List<OaEventDTO> eventList = new ArrayList<>();
        List<DateTime> dateTimes = DateUtil.rangeToList(new Date(startTime), new Date(endTime), DateField.DAY_OF_YEAR);
        for (DateTime day : dateTimes) {
            for (OaEvent oaEvent : oaEventList) {
                LocalDateTime endDate = oaEvent.getRepeatEndTime();
                long duration = LocalDateTimeUtil.toEpochMilli(oaEvent.getEndTime()) - LocalDateTimeUtil.toEpochMilli(oaEvent.getStartTime());
                if (isContinue(oaEvent, day.toLocalDateTime(), endDate)) {
                    continue;
                }
                if (LocalDateTimeUtil.toEpochMilli(oaEvent.getStartTime()) > day.getTime()) {
                    continue;
                }
                LocalDateTime offStartTime = DateUtil.parseLocalDateTime(DateUtil.formatDate(day) + " " + DateUtil.formatLocalDateTime(oaEvent.getStartTime()));

                long betweenMonth = LocalDateTimeUtil.between(oaEvent.getStartTime(), offStartTime, ChronoUnit.MONTHS);
                Integer repeatRate = oaEvent.getRepeatRate();
                if (betweenMonth % repeatRate != 0) {
                    continue;
                }
                String repeatTime = oaEvent.getRepeatTime();
                int repeatDate = Integer.parseInt(repeatTime);
                final int dd = Integer.parseInt(DateUtil.format(day, "dd"));
                if (dd == repeatDate) {
                    OaEventDTO oaEventDTO = transfer(oaEvent);
                    oaEventDTO.setStartTime(LocalDateTimeUtil.toEpochMilli(offStartTime));
                    oaEventDTO.setEndTime(LocalDateTimeUtil.toEpochMilli(offStartTime) + duration);
                    eventList.add(oaEventDTO);
                }
            }
        }
        return eventList;
    }

    @Override
    protected LocalDateTime processCountTime(LocalDateTime startTime, int offset) {
        return LocalDateTimeUtil.offset(startTime, offset, ChronoUnit.MONTHS);
    }
}
